//package com.game.ws;
//
//import com.game.gate.GateSession;
//import com.game.protobuf.PFMessage;
//import io.netty.buffer.ByteBuf;
//import io.netty.buffer.Unpooled;
//import io.netty.channel.ChannelFuture;
//import io.netty.channel.ChannelFutureListener;
//import io.netty.channel.ChannelHandlerContext;
//import io.netty.channel.SimpleChannelInboundHandler;
//import io.netty.handler.codec.http.DefaultFullHttpResponse;
//import io.netty.handler.codec.http.FullHttpRequest;
//import io.netty.handler.codec.http.HttpRequest;
//import io.netty.handler.codec.http.HttpResponseStatus;
//import io.netty.handler.codec.http.HttpVersion;
//import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
//import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
//import io.netty.handler.codec.http.websocketx.WebSocketFrame;
//import io.netty.handler.codec.http.websocketx.WebSocketServerHandshaker;
//import io.netty.handler.codec.http.websocketx.WebSocketServerHandshakerFactory;
//import io.netty.handler.timeout.IdleState;
//import io.netty.handler.timeout.IdleStateEvent;
//import io.netty.util.Attribute;
//import io.netty.util.AttributeKey;
//import io.netty.util.CharsetUtil;
//import io.netty.util.concurrent.GenericFutureListener;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//
//public class WebSocketServerHandler extends SimpleChannelInboundHandler {
//    Logger log = LoggerFactory.getLogger(getClass());
//
//    public void channelActive(ChannelHandlerContext ctx) throws Exception {
//        GateSession gateSession = new WSGateSession();
//        gateSession.channelActive(ctx);
//        GateSession.gateSessionMap.put(gateSession.sessionId, gateSession);
//    }
//
//    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
//        if (evt instanceof IdleStateEvent) {
//            String sessionId;
//            GateSession gateSession;
//            IdleStateEvent e = (IdleStateEvent)evt;
//            switch (e.state()) {
//                case READER_IDLE:
//                    sessionId = ctx.channel().id().asShortText();
//                    gateSession = (GateSession)GateSession.gateSessionMap.get(sessionId);
//                    if (gateSession != null) {
//                        this.log.warn("{},ctx={}", Long.valueOf(gateSession.activeTime), ctx);
//                    } else {
//                        this.log.warn("{}", ctx);
//                    }
//                    ctx.close();
//                    break;
//            }
//        } else {
//            super.userEventTriggered(ctx, evt);
//        }
//    }
//
//    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
//        String sessionId = ctx.channel().id().asShortText();
//        GateSession gateSession = (GateSession)GateSession.gateSessionMap.get(sessionId);
//        if (gateSession != null) {
//            gateSession.channelInactive(ctx);
//        } else {
//            ctx.close();
//        }
//    }
//
//    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
//        ctx.flush();
//    }
//
//    public String getRealIp(FullHttpRequest request) {
//        if (request.headers().contains("X-Forwarded-For"))
//            return request.headers().get("X-Forwarded-For");
//        if (request.headers().contains("x-forwarded-for"))
//            return request.headers().get("x-forwarded-for");
//        if (request.headers().contains("HTTP_X_FORWARDED_FOR"))
//            return request.headers().get("HTTP_X_FORWARDED_FOR");
//        if (request.headers().contains("X-Real_IP"))
//            return request.headers().get("X-Real_IP");
//        return request.headers().get("X-Real_IP");
//    }
//
//    protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
//        if (msg instanceof FullHttpRequest) {
//            this.log.debug("{},msg={}", ctx.channel().id(), msg);
//            FullHttpRequest fullHttpRequest = (FullHttpRequest)msg;
//            String ip = getRealIp(fullHttpRequest);
//            if (ip != null && ip.length() > 0) {
//                if (ip.contains(":")) {
//                    ip = ip.split(":")[0];
//                } else if (ip.contains(",")) {
//                    ip = ip.split(",")[0];
//                }
//                this.log.debug("ws {}", ip);
//                AttributeKey<String> attributeKey = AttributeKey.valueOf("X-Real_IP");
//                Attribute<String> attribute = ctx.channel().attr(attributeKey);
//                attribute.set(ip);
//            }
//            handleHttpRequest(ctx, (FullHttpRequest)msg);
//        } else if (msg instanceof WebSocketFrame) {
//            handlerWebSocketFrame(ctx, (WebSocketFrame)msg);
//        }
//    }
//
//    public void handlerWebSocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) throws Exception {
//        if (frame instanceof io.netty.handler.codec.http.websocketx.CloseWebSocketFrame) {
//            channelInactive(ctx);
//            return;
//        }
//        if (frame instanceof io.netty.handler.codec.http.websocketx.PingWebSocketFrame) {
//            ctx.channel().write(new PongWebSocketFrame(frame.content().retain()));
//            return;
//        }
//        if (frame instanceof BinaryWebSocketFrame) {
//            BinaryWebSocketFrame binaryWebSocketFrame = (BinaryWebSocketFrame)frame;
//            ByteBuf msg = frame.content();
//            decode(ctx, msg);
//        }
//    }
//
//    public void decode(ChannelHandlerContext ctx, ByteBuf msg) {
//        int messageType = msg.readUnsignedShort();
//        int cmd = msg.readUnsignedShort();
//        byte[] array = new byte[msg.readableBytes()];
//        msg.getBytes(msg.readerIndex(), array, 0, array.length);
//        PFMessage message = new PFMessage(messageType, cmd, array);
//        String sessionId = ctx.channel().id().asShortText();
//        GateSession gateSession = (GateSession)GateSession.gateSessionMap.get(sessionId);
//        if (gateSession != null)
//            gateSession.messageReceived(message);
//    }
//
//    public void handleHttpRequest(ChannelHandlerContext ctx, FullHttpRequest req) {
//        if (!req.decoderResult().isSuccess()) {
//            sendHttpResponse(ctx, req, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST));
//            return;
//        }
//        WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory("ws:/" + ctx.channel() + "/websocket", null, false);
//        WebSocketServerHandshaker handshaker = wsFactory.newHandshaker((HttpRequest)req);
//        if (handshaker == null) {
//            WebSocketServerHandshakerFactory.sendUnsupportedVersionResponse(ctx.channel());
//        } else {
//            handshaker.handshake(ctx.channel(), req);
//        }
//    }
//
//    public static void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest req, DefaultFullHttpResponse res) {
//        if (res.status().code() != 200) {
//            ByteBuf buf = Unpooled.copiedBuffer(res.status().toString(), CharsetUtil.UTF_8);
//            res.content().writeBytes(buf);
//            buf.release();
//        }
//        ChannelFuture f = ctx.channel().writeAndFlush(res);
//        if (!isKeepAlive(req) || res.status().code() != 200)
//            f.addListener((GenericFutureListener)ChannelFutureListener.CLOSE);
//    }
//
//    private static boolean isKeepAlive(FullHttpRequest req) {
//        return false;
//    }
//
//    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//        cause.printStackTrace();
//        ctx.close();
//    }
//}
